#pragma once
#include "event/event.hpp"

#include <cassert>
#include <cstdint>
#include <functional>
#include <iostream>
#include <utility>
#include <memory>

#include <sys/epoll.h>

namespace ibox::event {
class Loop;
class EpollLoop;
class EpollFdSharedData;

class FdEvent : public Event {
    using CallbackFunc = std::function<void(uint32_t events)>;

public:
    enum EventTypes {
        ReadEvent = 0x01,
        WriteEvent = 0x02,
        ExceptEvent = 0x04,
    };
};

class EpollFdEvent {
    using CallbackFunc = std::function<void(uint32_t events)>;

public:
    EpollFdEvent(EpollLoop *loop, int fd, uint32_t events, Event::Mode mode);
    //~EpollFdEvent() = default;
    ~EpollFdEvent() { std::cout << "~EpollFdEvent()\n"; };
    void set_callback(CallbackFunc cb) { m_cb = std::move(cb); }
    bool is_enabled() const { return m_is_enabled; }
    bool enable();
    bool disable();
    Loop *get_loop();

public:
    static void on_event_callback(int fd, uint32_t events, void *obj);

private:
    void reload_epoll();
    void on_event(uint32_t events);
    void unref_fd_shared_data();

private:
    EpollLoop *m_loop{};
    int m_fd = -1; // TODO: FdEvent公共类中
    bool m_is_enabled{};
    bool m_is_stop_after_trigger{};
    uint32_t m_events{};
    Event::Mode m_mode = Event::Mode::Oneshot;
    CallbackFunc m_cb{};
    std::shared_ptr<EpollFdSharedData> m_data{};
};

// 同一个fd共享的数据
class EpollFdSharedData {
public:
    int ref = 0;
    epoll_event ev;
    std::vector<EpollFdEvent *> read_events;
    std::vector<EpollFdEvent *> write_events;
};

} // namespace ibox::event
